home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-04 | 6.1 KB | 236 lines | [TEXT/MPCC] |
- // Sound Object Handler for the WASTE Text Engine
- // by Michael F. Kamprath, kamprath@earthlink.net
- // and Chris K. Thomas, ckt@guest.apple.com
- // or thunderone@delphi.com
- //
- // History:
- // v1.0, 16 March 1995 MFK - created
- //
- // v2.0b1: 11 May 1995 CKT
- // almost entirely rewritten for robustness, simplicity,
- // modularity and some flexibility
- // v2.0b2: 2-3 June 1995 CKT
- // bug fixes & now works on 68k and minor tweaking.
- //
-
- /*
- Features of the new implementation:
-
- • Single click only. The previous one wanted double
- click. To the user, this is like pressing a button,
- which is a single click operation.
-
- • Improved memory management.
-
- • Added method to stop the currently playing sound.
-
- • Removed a bunch of unnecessary methods.
-
- • Cleaned up the global namespace.
-
- • Can now use any size (square) icon.
-
- • Managed to resist the temptation to C++-ify. I
- have a great stack-based SndCommand class, though...
-
- In general, we just pollute our environment less and
- manage to run faster anyway. Industrial Strength and
- non-toxic.
-
- - Chris
- */
-
- #include <Icons.h>
- #include <SoundInput.h>
- #include "WASTE.h"
-
- #include "WEObjectSound.h"
-
- // • constants =====================================================================
-
- #define kSoundIconID 550
- #define kIconSize 16 // * change to 32 for large
-
- // • macros ========================================================================
-
- #define ThrowIfOSErr_(x) if(x != noErr) goto end;
- // * well, okay, I couldn't help using C++ semantics, but there isn't any real C++...
-
- // • static variables ==============================================================
-
- static SndChannelPtr sSoundChannel = NULL;
- static SndListHandle sCurrentSound = NULL;
- static char sPreviousSoundState;
-
- // • static prototypes =============================================================
-
- static pascal OSErr HandleNewSound(Point *defaultObjectSize, WEObjectReference objectRef);
- static pascal OSErr HandleDisposeSound(WEObjectReference objectRef );
- static pascal Boolean HandleClickSound(Point hitPt, short modifiers,
- long clickTime, WEObjectReference objectRef);
- static pascal OSErr HandleDrawSound(Rect *destRect, WEObjectReference objectRef );
-
-
- // • mixedmode =====================================================================
-
- static UniversalProcPtr sNewHandlerRD = NULL;
- static UniversalProcPtr sDisposeHandlerRD = NULL;
- static UniversalProcPtr sDrawHandlerRD = NULL;
- static UniversalProcPtr sClickHandlerRD = NULL;
-
- // • implementation ===============================================================
-
- // * Install the sound object handlers
- // * if inChannel is NULL, we create our own.
- // * if not, we use inChannel.
-
- OSErr WEObjSoundInstall(SndChannelPtr inChannel, WEHandle inWaste)
- {
- OSErr theErr = noErr;
-
- if(sNewHandlerRD == NULL)
- {
- sNewHandlerRD = NewWENewObjectProc(HandleNewSound);
- sDisposeHandlerRD = NewWEDisposeObjectProc(HandleDisposeSound);
- sDrawHandlerRD = NewWEDrawObjectProc(HandleDrawSound);
- sClickHandlerRD = NewWEClickObjectProc(HandleClickSound);
- }
-
- if(inChannel == NULL)
- {
- theErr = SndNewChannel(&sSoundChannel, sampledSynth, 0, NULL);
- ThrowIfOSErr_(theErr);
- }
- else
- {
- sSoundChannel = inChannel;
- }
-
- theErr = WEInstallObjectHandler('snd ', weNewHandler, sNewHandlerRD, inWaste);
- ThrowIfOSErr_(theErr);
- theErr = WEInstallObjectHandler('snd ', weDisposeHandler, sDisposeHandlerRD, inWaste);
- ThrowIfOSErr_(theErr);
- theErr = WEInstallObjectHandler('snd ', weDrawHandler, sDrawHandlerRD, inWaste);
- ThrowIfOSErr_(theErr);
- theErr = WEInstallObjectHandler('snd ', weClickHandler, sClickHandlerRD, inWaste);
- ThrowIfOSErr_(theErr);
-
- end:
- return theErr;
- }
-
- // * New Object Handler for sounds
- pascal OSErr HandleNewSound(Point *defaultObjectSize, WEObjectReference /*objectRef*/)
- {
- (*defaultObjectSize).h = kIconSize;
- (*defaultObjectSize).v = kIconSize;
-
- return noErr;
- }
-
- // * Dispose Object handler for sounds
- pascal OSErr HandleDisposeSound(WEObjectReference objectRef)
- {
- SndListHandle theSound;
-
- theSound = (SndListHandle)WEGetObjectDataHandle(objectRef);
-
- if(theSound == sCurrentSound) //MFK fix
- WEObjSoundStop();
-
- DisposeHandle((Handle)theSound);
-
- return MemError();
- }
-
- // * Draw Object handler for sounds
- pascal OSErr HandleDrawSound(Rect *destRect, WEObjectReference /*objectRef*/ )
- {
- OSErr theErr;
-
- theErr = PlotIconID(destRect, atNone, ttNone, kSoundIconID);
-
- return theErr;
- }
-
- // * Click Object Handler for sounds
- pascal Boolean
- HandleClickSound(Point /*hitPt*/, short /*modifiers*/,
- long /*clickTime*/, WEObjectReference objectRef)
- {
- if(sCurrentSound)
- {
- WEObjSoundStop();
- }
-
- sCurrentSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
-
- sPreviousSoundState = HGetState((Handle)sCurrentSound);
- HLockHi((Handle)sCurrentSound);
-
- SndPlay(sSoundChannel, sCurrentSound, true);
-
- return true;
- }
-
- // • global sound utils ===============================================================
-
- // * Uses built in sound recording to create a new sound object.
- OSErr WEObjSoundNew( WEHandle theWE )
- {
- OSErr theErr;
- SndListHandle sndHandle = nil;
- Point corner = {kIconSize, kIconSize};
-
- theErr = SndRecord(nil, corner, siGoodQuality, &sndHandle);
-
- if (theErr == noErr)
- {
- corner.h = kIconSize;
- corner.v = kIconSize;
- WEInsertObject( 'snd ', (Handle)sndHandle, corner, theWE );
- }
-
- return( theErr );
- }
-
- // * idle - Call this at some point in your event loop
- // * or through an idle queue etc
- void WEObjSoundIdle(void)
- {
- if(sCurrentSound)
- {
- SCStatus curStatus;
-
- SndChannelStatus(sSoundChannel, sizeof(SCStatus), &curStatus);
-
- if(!curStatus.scChannelBusy)
- HSetState((Handle)sCurrentSound, sPreviousSoundState);
- }
- }
-
- // * stop the sound in progress, if any
- void WEObjSoundStop(void)
- {
- if(sCurrentSound)
- {
- SCStatus curStatus;
-
- SndChannelStatus(sSoundChannel, sizeof(SCStatus), &curStatus);
-
- if(curStatus.scChannelBusy)
- {
- SndCommand ourCmd;
-
- ourCmd.cmd = quietCmd;
- ourCmd.param1 = 0;
- ourCmd.param2 = 0;
-
- (void) SndDoImmediate(sSoundChannel, &ourCmd);
- HSetState((Handle)sCurrentSound, sPreviousSoundState);
-
- // * yes, we're ignoring the error purposely
-
- }
- }
- }